Next Previous Table of Contents

The BMath Class

#include "bmath.hxx"

Who is this Class for?

Who is this Class not for?

If this is you, you will lose nothing by skipping this section and going directly to the section on the
LInteger class.

Required Representation of Magnitudes

Methods which operate on magnitudes must have these magnitudes stored in exactly the same format described for magnitudes in the LInteger class. An exception to this rule is that lead zeros are ok here, except where noted otherwise. See the magnitude section of the internal representation section for details.

Basic Algorithms

These two algorithms are not directly implemented, but, nevertheless, are useful in explaining how the methods in the BMath class work:

The Ripple Carry Algorithm

Given a starting location start, rippling a carry works as given by the following pseudo-code:
	  set carry flag;
	  unsigned int* mem=start;
	  while (carry flag)
	  {
             (*mem)++;
             if (overflow)
	        set carry flag; 
	     else 
                clear carry flag;
	     mem--;
	  }
      

The Ripple Carry Algorithm

Given a starting location start, rippling a borrow works as given by the following pseudo-code:
	  set borrow flag;
	  unsigned int* mem=start;
	  while (borrow flag)
	  {
             (*mem)--;
             if (borrow)
                set borrow flag;
             else
                clear borrow flag;
	     mem--;
	  }
      

Public Methods

GreaterThanOrEqualTo

static inline char BMath::GreaterThanOrEqualTo(const unsigned int* A, const unsigned int* B, const int size)

Compares two magnitudes, returning 1 if the magnitude pointed to by A is greater than or equal to the magnitude pointed to by B and 0 otherwise.

A and B must have the same number of digits. This number is specified by size.

BasicAdd

static inline void BMath::BasicAdd(const unsigned int* A, const unsigned int* B, unsigned int* C, const int size, char& carry)

Adds the magnitude pointed to by A to the mangitude pointed to by B, and stores the size least significant digits of the result into the memory segment pointed to by C. If the addition results in a carry, carry is set to 1, otherwise it is set to 0.

A and B must have the same number of digits. This number is specified by size.

Add

static void BMath::Add(const unsigned int* A, const unsigned int* B, unsigned int* C, const int sizeOfA, const int sizeOfB, char& carry)

Adds the sizeOfB digit mangitude pointed to by B to the sizeOfA digit mangitude point to by A. The magnitude pointed to by A must have at least as many digits as the magnitude pointed by B for this to work. The sizeOfA least significant digits of the sum are stored into memory starting at the location pointed to by C. If the sum is a sizeOfA+1 digit number, carry is set to 1, otherwise it is set to 0.

RippleAdd

static inline void BMath::RippleAdd(const unsigned int* A, const unsigned int* B, unsigned int* C, const int size)

Adds the magnitude pointed to by A to the mangitude pointed to by B, and stores the size least significant digits of the result into the memory segment pointed to by C. If the addition results in a carry, it is rippled as described in the ripple carry algorithm with a start point equal to C-1.

A and B must have the same number of digits. This number is specified by size.

BasicSubtract

static inline void BMath::BasicSubtract(const unsigned int* A, const unsigned int* B, unsigned int* C, const int size, char& borrow)

Subtracts the magnitude pointed to by B from the mangitude pointed to by B, and stores size least significant digits of the result into the memory segment pointed to by C. If the subtraction requires a borrow, borrow is set to 1, otherwise it is set to 0.

A and B must have the same number of digits. This number is specified by size.

Subtract

static void BMath::Subtract(const unsigned int* A, const unsigned int* B, unsigned int* C, const int sizeOfA, const int sizeOfB)

Subtracts the sizeOfA digit magnitude pointed to by B from the sizeOfB digit mangitude pointed to by B, and stores the sizeOfA least significant digits of the result into memory starting at the address pointed to by C. The magnitude poitned to by A must be greater than or equal to the magnitude to by B and must have at least as many digits for this method to work.

RippleSubtract

static inline void BMath::RippleSubtract(const unsigned int* A, const unsigned int* B, unsigned int* C, const int size)

Subtracts the magnitude pointed to by B from the mangitude pointed to by A, and stores size least significant digits of the magnitude of the result into the memory segment pointed to by C. If the subtraction requires in a borrow, it is rippled as descirbed in the ripple borrow algorithm with a start point equal to C-1.

A and B must have the same number of digits. This number is specified by size.

Increment

static inline void BMath::Increment(unsigned int* linteger, const int size, char& carry)

Icrements the size digit magnitude pointed to by linteger by 1. If this increment result in a carry, carry is set to 1, otherwise carry is set to 0.

RippleIncrement

static inline void BMath::RippleIncrement(unsigned int* linteger, const int size)

Icrements the size digit magnitude pointed to by linteger by 1. If this increment result in a carry, it is rippled out via the ripple carry algorithm with a start point equal to linteger-1.

RippleDecrement

static inline void BMath::RippleDecrement(unsigned int* linteger, const int size)

Decrements the size digit magnitude pointed to by linteger by 1. If this decrement results in a borrow, it is rippled out via the ripple borrow algorithm with a start point equal to linteger-1.

BasicMultiply

static inline void BMath::BasicMultiply(const unsigned int* A, unsigned int B, unsigned int* C, const int sizeA)

Multiplies the sizeA digit magnitude pointed to by A by B and adds the sizeA+1 digit result to the sizeA+1 digit magnitude pointed at by C, storing the lower sizeA+1 digits of the result in the meomry location pointed to by C. If this addition results in a carry it is rippled out via the ripple carry algorithm with a start point equal to C-1.

C must not be equal to A for this method to work.

MultDouble

static inline void BMath::MultDouble(unsigned int* productBuf, const unsigned int* a, const unsigned int* b)

Multplies the two digit magnitude pointed to by a by the two digit magnitude pointed to by b. The four digit result is stored starting at the memory location pointed to by productbuf.

SquareDouble

static inline void BMath::SquareDouble(unsigned int* productBuf, const unsigned int* a)

Squares the two digit magnitude pointed to by a, and stores the four digit starting at the memory location pointed to by productbuf. This is method is equivalent to Mult64(productBuf,a,a), except that it is a bit faster.

Multiply

static void BMath::Multiply(const unsigned int* A, int sizeA, const unsigned int* B, int sizeB, unsigned int* result)

Multiplies the sizeA digit magnitude pointed to by A by the sizeB digit magnitude pointed to by B and stores the sizeA+sizeB digit result starting at the memory location pointed to by result. In order for this to work, the memories locations from result to result+sizeA+sizeB-1 inclusive must be zero before this method is called.

Square

static void BMath::Square(const unsigned int* a, const int sizeA, unsigned int* result)

Squares the sizeA digit magnitude pointed to by A and stores the 2*sizeA result starting at the memory location pointed to by result. In order for this to work, the memories locations from result to result+2*sizeA-1 must be zero before this method is called. This method is equivalent to Multiply(a,sizeA,a,sizeA,result) except that it is a bit faster.

BasicDivide

static inline void BMath::BasicDivide(unsigned int dividendHigh, unsigned int dividendLow, unsigned int divisor, unsigned int& quotient, unsigned int& remainder)

Divides the two digit dividend given by dividendHigh*base+dividendLow by divisor. the quotient is stored in quotient and the remainder is stored in remainder. (Shocking, huh? :) ) Be careful that the quotient can fit in an unsigned int before calling this method, or you'll get a floating exception.

Divide

static void BMath::Divide(const unsigned int* divisor, const int divisorSize, const unsigned int* dividend, const int dividendSize, unsigned int*& quotient, unsigned int*& remainder)

Divides the dividendSize digit dividend by the dividendSize digit divisor. Upon return, quotient points to a dynamically allocated memory block containing the dividendSize-divisorSize+1 digit magnitude of the quotient. remainder, on the other hand, points to a dynamically allocated memory block of dividendSize+1 digits, the divisorSize least significant of which will be magnitude of the remainder, and the dividendSize-divisorSize+1 most significant of which will be zero.

The caller is assumed to own the memory pointed to by quotient, and remainder after this method is called, and, as such, is responsible for freeing it. Warning: The interface to this method will almost surely change in the next version of this library so that the caller will be responsible for allocating the dynamic memory to store the results before calling the method.

Note:

dividendSize must be greater than or equal to divisorSize for this method to work. The magnitude pointed to by the divisor may not have lead zeros.

BSR

static inline int BMath::BSR(unsigned int x)

Returns the bit position (0-31, 0 being least significant) of the most significant bit which is 1 in x.

Normalize

static inline char BMath::Normalize(unsigned int* buf, int size)

Shifts the bits of the size digit magnitude pointed to by buf the minimum number of digits left to bring a 1 into the most significant bit. Zeros are brought in on the right. The magnitude pointed to by buf must a least one bit equal to 1 its most significant digit for this work. The value returned is equal to the distance of the shift.

ShiftLeft

static inline void BMath::ShiftLeft(unsigned int* buf, int size, char distance)

Shifts the bits of the size digit magnitude pointed to by buf left by the number of positions given by the 5 least significant bits of distance. Zeros are shifted in on the right, while bits shifted out on the left are lost.

ShiftRight

static inline void BMath::ShiftRight(unsigned int* buf, int size, char distance)

Shifts the binary digits of the size digit magnitude pointed to by buf right by the number of positions given by the 5 least significant bits of distance. Zeros are shifted in on the left, while bits shifted out on the right are lost.


Next Previous Table of Contents